package classfile

// 表示各种属性的接口
type AttributeInfo interface {
	readInfo(reader *ClassReader)
}

func readAttributes(reader *ClassReader, cp ConstantPool) []AttributeInfo {
	// 属性个数
	attrCount := reader.ReadUint16()
	infos := make([]AttributeInfo, attrCount)
	for i := range infos {
		infos[i] = readAttribute(reader, cp)
	}
	return infos
}

// 读取属性
func readAttribute(reader *ClassReader, cp ConstantPool) AttributeInfo {
	// 属性名称的索引，是对常量池的有效索引，常量池此位置上必须是一个UTF8结构，代表此属性的名称
	attrNameIndex := reader.ReadUint16()
	// 从常量池中获取属性名称
	attrName := cp.getUtf8(attrNameIndex)
	// 获取属性长度
	attrLen := reader.ReadUint32()
	// 根据不同的属性名称创建不同的属性结构体
	attributeInfo := newAttributeInfo(attrName, attrLen, cp)
	// 读取指定长度个字节
	attributeInfo.readInfo(reader)
	return attributeInfo

}

func newAttributeInfo(attrName string, attrLen uint32, cp ConstantPool) AttributeInfo {
	switch attrName {
	case "Code":
		return &CodeAttribute{cp: cp}
	case "Deprecated":
		return &DeprecatedAttribute{}
	case "Synthetic":
		return &SyntheticAttribute{}
	case "SourceFile":
		return &SourceFileAttribute{cp: cp}
	case "ConstantValue":
		return &ConstantValueAttribute{}
	case "Exception":
		return &ExceptionAttribute{}
	default:
		return &UnparseAttribute{attrName, attrLen, nil}
	}
}
